package com.gy.utils;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import com.gy.properties.AliOssProperties; // 引入 AliOssProperties

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 阿里云 OSS 工具类
 */
@Component
public class AliOSSUtils {

    private final AliOssProperties aliOssProperties; // 注入 AliOssProperties

    public AliOSSUtils(AliOssProperties aliOssProperties) {
        this.aliOssProperties = aliOssProperties;
    }

    // 分片大小，单位为字节，这里设置为5MB
    private static final int PART_SIZE = 50 * 1024 * 1024;

    /**
     * 实现上传图片到OSS
     */
    public String upload(MultipartFile file) throws IOException {
        long fileSize = file.getSize();
        if (fileSize > PART_SIZE) {
            return multipartUpload(file);
        } else {
            return simpleUpload(file);
        }
    }

    /**
     * 实现上传图片到OSS,设置文件为追加上传
     */
    public String uploadAppend(MultipartFile file, boolean isAppendable) throws IOException {
        long fileSize = file.getSize();
        if (fileSize > PART_SIZE) {
            return multipartUpload(file);
        } else {
            return simpleUploadAppend(file, isAppendable);
        }
    }

    /**
     * 普通上传
     */
    private String simpleUpload(MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();
        String originalFilename = file.getOriginalFilename();
        String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));

        OSS ossClient = new OSSClientBuilder().build(aliOssProperties.getEndpoint(), aliOssProperties.getAccessKeyId(), aliOssProperties.getAccessKeySecret());
        ossClient.putObject(aliOssProperties.getBucketName(), fileName, inputStream);
        ossClient.shutdown();

        return buildFileUrl(fileName);
    }

    /**
     * 追加上传
     */
    private String simpleUploadAppend(MultipartFile file, boolean isAppendable) throws IOException {
        InputStream inputStream = file.getInputStream();
        String originalFilename = file.getOriginalFilename();
        String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));

        OSS ossClient = new OSSClientBuilder().build(aliOssProperties.getEndpoint(), aliOssProperties.getAccessKeyId(), aliOssProperties.getAccessKeySecret());

        if (isAppendable) {
            long position = 0;
            AppendObjectRequest appendObjectRequest = new AppendObjectRequest(aliOssProperties.getBucketName(), fileName, inputStream);
            appendObjectRequest.setPosition(position);
            AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);
        } else {
            ossClient.putObject(aliOssProperties.getBucketName(), fileName, inputStream);
        }

        ossClient.shutdown();

        return buildFileUrl(fileName);
    }

    /**
     * 分片上传
     */
    private String multipartUpload(MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
        long fileSize = file.getSize();

        OSS ossClient = new OSSClientBuilder().build(aliOssProperties.getEndpoint(), aliOssProperties.getAccessKeyId(), aliOssProperties.getAccessKeySecret());

        // 初始化分片上传
        InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(aliOssProperties.getBucketName(), fileName);
        InitiateMultipartUploadResult initResult = ossClient.initiateMultipartUpload(initRequest);
        String uploadId = initResult.getUploadId();

        List<PartETag> partETags = new ArrayList<>();
        try (InputStream inputStream = file.getInputStream()) {
            byte[] buffer = new byte[PART_SIZE];
            int partNumber = 1;
            int bytesRead;

            while ((bytesRead = inputStream.read(buffer)) != -1) {
                ByteArrayInputStream partInputStream = new ByteArrayInputStream(buffer, 0, bytesRead);
                UploadPartRequest uploadPartRequest = new UploadPartRequest();
                uploadPartRequest.setBucketName(aliOssProperties.getBucketName());
                uploadPartRequest.setKey(fileName);
                uploadPartRequest.setUploadId(uploadId);
                uploadPartRequest.setInputStream(partInputStream);
                uploadPartRequest.setPartSize(bytesRead);
                uploadPartRequest.setPartNumber(partNumber++);

                // 上传分片
                UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
                partETags.add(uploadPartResult.getPartETag());
            }

            // 完成分片上传
            CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(aliOssProperties.getBucketName(), fileName, uploadId, partETags);
            ossClient.completeMultipartUpload(completeRequest);

        } catch (Exception e) {
            // 上传失败时的异常处理
            ossClient.abortMultipartUpload(new AbortMultipartUploadRequest(aliOssProperties.getBucketName(), fileName, uploadId));
            throw e;
        } finally {
            ossClient.shutdown();
        }

        return buildFileUrl(fileName);
    }


    /**
     * 构建文件访问路径
     */
    private String buildFileUrl(String fileName) {
        String endpoint = aliOssProperties.getEndpoint();
        // 移除 endpoint 中可能包含的协议前缀（如 http:// 或 https://）
        String cleanEndpoint = endpoint.replaceAll("^https?://", "");
        return "https://" + aliOssProperties.getBucketName() + "." + cleanEndpoint + "/" + fileName;
    }
}
